[TOC]

Assignment with Subscripts

When assigning values to array elements, we can use an expression of the form A(s1, s2, ..., sk) = b. This is known as subscript indexing. The arrays s1, s2, ..., sk are called index arrays, which specify an element or a subarray of A to be replaced by b. We call b the right-hand side of the assignment.

The assignment can have different behaviours, depending on the sizes of the involved arrays. Our objective here is to exhaust all possible scenarios for the sake of completeness.

Basic Usages

One simple example of subscript array assignment is A(1, 1, 1) = 2, which assigns 2 to the element A(1, 1, 1). In this assign, just one element of A is replaced. A common usage is to replace a subarray of A by an array. This can be achieved by including multiple indexes in the index arrays. For example, the following assignment replaces the top-left subarray of the matrix A by negative values:

Input
A = [1 2 3; 4 5 6; 7 8 9];
A([1 2], [1 2]) = [-1 -2; -4 -5]
Output
A = 
-1.0000  -2.0000   3.0000
-4.0000  -5.0000   6.0000
 7.0000   8.0000   9.0000

Sizes of Index Arrays and b

Before performing an assignment, each of the index arrays is reshaped to a vector. Hence, the sizes of the index arrays are not important. However, the index arrays must represent an subarray that has the same size as b. This requirement can be relaxed when b is a scalar or empty. In the former case, b is expanded to match the size. The latter case is called null assignment. Both of them will be discussed in the sections below.

In the following example, [1; 2] and [1 2; 3 4] are reshaped to [1 2] and [1 3 2 4], respectively. The array b and the subarray specified by [1 2] and [1 3 2 4] have the same sizes.

Input
A = rand(2,5,2);
b = [-1 -2 -3 -4; -5 -6 -7 -8];
A([1; 2],[1 2; 3 4],2) = b 
Output
A(:, :, 1) = 
 0.4655   0.5819   0.5825   0.8423   0.2375
 0.0093   0.5478   0.7428   0.1291   0.0677

A(:, :, 2) = 
-1.0000  -3.0000  -2.0000  -4.0000   0.2977
-5.0000  -7.0000  -6.0000  -8.0000   0.2813

A Not Yet Defined

When the variable A does not exist yet, it will be created with the smallest possible size to fit the given index arrays and the right-hand side b. The example below illustrates this idea. First, all variables are clear to make sure that A does not exist yet. Then, A is created with the smallest possible size to fit the assigned value 9.

Input
clear
A(2,2:3,2) = 999
Output
All variables cleared
A(:, :, 1) = 
 0.0000   0.0000   0.0000
 0.0000   0.0000   0.0000

A(:, :, 2) = 
 0.0000   0.0000   0.0000
 0.0000   999.00   999.00

It is not mandatory to give all index arrays explicitly. If possible, the size of A is inferred from the given b. The following example illustrates this idea, in which index arrays for the first two dimensions are not given. Therefore, their lengths are infered from b.

Input
clear
A(:,:,3) = [1 2;3 4]
Output
All variables cleared
A(:, :, 1) = 
 0.0000   0.0000
 0.0000   0.0000

A(:, :, 2) = 
 0.0000   0.0000
 0.0000   0.0000

A(:, :, 3) = 
 1.0000   2.0000
 3.0000   4.0000

Empty Index Array

When any of s1, s2, ... sk is empty, it is equivalent to an empty subarray. That means, none of the elements of A is indexed, and hence A does not change at all.

Input
A = rand(3,5)
A([1 2],[]) = 6
Output
A = 1e-1 × 
 0.2029   4.0065   7.8841   8.8348   6.9380
 6.5175   5.8852   4.8361   1.5619   3.3200
 3.3422   8.9819   4.3727   0.4274   8.0099

A = 1e-1 × 
 0.2029   4.0065   7.8841   8.8348   6.9380
 6.5175   5.8852   4.8361   1.5619   3.3200
 3.3422   8.9819   4.3727   0.4274   8.0099

In the example below, one of the index arrays is empty. Although the right-hand size is empty (Line 7), null assignment is not performed. It simply returns the same array (Line 9)÷.

Input
% Random array
a = rand(3,4,2);
% Duplicate a
b = a;
% Assignment with an empty index array.
a([],:,:)=[];
% The array remains unchanged.
a == b
Output
ans(:, :, 1) = 
1  1  1  1
1  1  1  1
1  1  1  1

ans(:, :, 2) = 
1  1  1  1
1  1  1  1
1  1  1  1

Fewer Index Arrays Than ndims(A)

In the assignment A(s1, s2, ..., sk) = b, if k < ndims(A), then sn is assumed 1 for all n equal to k+1, k+2, ..., ndims(A). In the example below, the array index for the 3rd is not given explicitly. Hence, it is assumed 1.

Input
A = rand(3,4,2)
A(1,3)=-7
Output
A(:, :, 1) = 1e-1 ×
 2.3501   3.6036   3.1581   1.3895
 7.1976   1.0994   4.1380   5.2222
 9.7043   9.0874   6.5067   2.9019

A(:, :, 2) = 1e-1 ×
 0.0645   1.3826   7.1434   4.1324
 7.7113   2.3086   7.0049   3.2586
 0.9472   7.4510   3.0175   2.2462

A(:, :, 1) = 
 0.2350   0.3604  -7.0000   0.1390
 0.7198   0.1099   0.4138   0.5222
 0.9704   0.9087   0.6507   0.2902

A(:, :, 2) = 
 0.0064   0.1383   0.7143   0.4132
 0.7711   0.2309   0.7005   0.3259
 0.0947   0.7451   0.3018   0.2246

More Index Arrays Than ndims(A)

In the assignment A(s1, s2, ..., sk) = b, if k > ndims(A) and the extra index arrays are not 1, A will be expanded to have a higher dimension. In the example below, the array A is expanded to a 3D array before the assignment.

Input
A = rand(3,4)
A(1,3,2) = -8
Output
A = 1e-1 × 
 9.9068   4.0765   6.9729   2.2716
 9.7742   1.1303   1.2514   8.8497
 5.8256   8.5381   9.7877   5.8365

A(:, :, 1) = 
 0.9907   0.4077   0.6973   0.2272
 0.9774   0.1130   0.1251   0.8850
 0.5826   0.8538   0.9788   0.5836

A(:, :, 2) = 
 0.0000   0.0000  -8.0000   0.0000
 0.0000   0.0000   0.0000   0.0000
 0.0000   0.0000   0.0000   0.0000

Expanding A When Too Small

Like what we have just seen in the above, if necesary, A will be expanded to fit the index arrays. More specifically, if sk has an index larger than size(A, k), the size of A is expanded by filling with zeros. In the example below, A is expanded in the vertical direction (1st dimension) to accommodate the 3rd and 4th rows.

Input
A = rand(2,5,3)
A([3,4],2,2) = [1 6]
Output
A(:, :, 1) = 1e-1 ×
 4.9653   8.2130   3.7269   8.6796   4.2001
 0.4117   4.2999   0.4666   4.8402   6.5270

A(:, :, 2) = 1e-1 ×
 4.6095   5.1983   5.2360   3.0258   2.0554
 0.2252   8.4777   5.7955   9.9402   0.0656

A(:, :, 3) = 1e-1 ×
 4.6372   3.1206   6.7108   2.3275   0.1238
 0.4289   2.1521   2.2372   9.3843   4.8929

A(:, :, 1) = 
 0.4965   0.8213   0.3727   0.8680   0.4200
 0.0412   0.4300   0.0467   0.4840   0.6527
 0.0000   0.0000   0.0000   0.0000   0.0000
 0.0000   0.0000   0.0000   0.0000   0.0000

A(:, :, 2) = 
 0.4609   0.5198   0.5236   0.3026   0.2055
 0.0225   0.8478   0.5796   0.9940   0.0066
 0.0000   1.0000   0.0000   0.0000   0.0000
 0.0000   6.0000   0.0000   0.0000   0.0000

A(:, :, 3) = 
 0.4637   0.3121   0.6711   0.2327   0.0124
 0.0429   0.2152   0.2237   0.9384   0.4893
 0.0000   0.0000   0.0000   0.0000   0.0000
 0.0000   0.0000   0.0000   0.0000   0.0000

b Is Empty

When b is empty, elements will be deleted from A. To make sure that A still has a valid (rectangular) size after deletion, only one dimension should be partially indexed. In the example below, we remove the 3rd row from all other dimensions. Only the 1st dimension (vertical direction) is partially indexed. The size was [3, 5, 3] before deletion and now becomes [2, 5, 3] after deletion.

delete1

Input
A = rand(3,5,3)
disp('After deletion')
% Only partially index dimension 1.
A(3,:,:) = []
Output
A(:, :, 1) = 1e-1 ×
 0.5117   6.9574   1.9861   6.6254   0.8575
 9.6222   8.0328   1.0864   5.4329   9.6185
 7.0200   7.7455   9.8031   4.5647   5.0340

A(:, :, 2) = 1e-1 ×
 7.4000   2.3109   2.9073   7.5566   2.7803
 0.0967   1.9684   2.2475   6.2314   3.0988
 1.6926   1.7482   8.7412   8.6907   5.3534

A(:, :, 3) = 1e-1 ×
 6.2877   2.4027   7.4572   1.8283   0.5045
 1.7432   2.5477   3.2167   8.6770   9.7168
 4.0055   1.5047   9.9842   0.9546   6.9831

After deletion

A(:, :, 1) = 1e-1 ×
 0.5117   6.9574   1.9861   6.6254   0.8575
 9.6222   8.0328   1.0864   5.4329   9.6185

A(:, :, 2) = 1e-1 ×
 7.4000   2.3109   2.9073   7.5566   2.7803
 0.0967   1.9684   2.2475   6.2314   3.0988

A(:, :, 3) = 1e-1 ×
 6.2877   2.4027   7.4572   1.8283   0.5045
 1.7432   2.5477   3.2167   8.6770   9.7168

💡 If at least one of the elements along a dimension are not indexed, we say that the dimension is partially indexed. For examples,

a = rand(2,3,4,5)
% In both cases below, Dim 1 is partially indexed, 
% and the rest of the dimension are fully indexed.
a(2, :, 1:end, 1:5)
a([], :, 1:end, 1:5)

If we attempt to remove just a "corner" of A, as shown in the figure below, the 1st and 2nd dimensions should both be partially indexed. Such an assignment will fail because the size would be invalid (not rectangular) if the corner is deleted.

delete2

This is illustrated in the figure and code below.

Input
A = rand(3,5,3);
disp('After deleting')
% Partially indexing 1st and 2nd dimensions.
A([2 3],[4 5],:) = []
Output
After deleting

Error at Line 5(1). At most one partially indexed dimension is expected in a null assignment.

b is Scalar

If b is a scalar, all elements in the subarray indexed by s1, s2, ... sk are changed to b.

Input
A = rand(3,5);
A([1 2],[3]) = 6
Output
A = 
 0.6935   0.1276   6.0000   0.7292   0.8989
 0.6482   0.5412   6.0000   0.7308   0.2232
 0.3938   0.2614   0.2234   0.4919   0.6319

b is Vector

When b is a vector, the subarray should be a vector of the same length. Whether b is a row or column vector, it does not matter. In the following example, the index array is a column vector but b can be a row or a column vector. It still works.

Input
A = rand(2,5,2);
% Make a copy of A
K = A;
% b is a row vector
A([1 2],1,2) = [1 2]
% b is a column vector
K([1 2],1,2) = [1; 2]
% K and A should be the same
Output
A(:, :, 1) = 
 0.9802   0.5235   0.7864   0.1015   0.9280
 0.8883   0.6972   0.4627   0.6704   0.5161

A(:, :, 2) = 
 1.0000   0.1449   0.2075   0.0928   0.5996
 2.0000   0.6372   0.5006   0.7598   0.9435

K(:, :, 1) = 
 0.9802   0.5235   0.7864   0.1015   0.9280
 0.8883   0.6972   0.4627   0.6704   0.5161

K(:, :, 2) = 
 1.0000   0.1449   0.2075   0.0928   0.5996
 2.0000   0.6372   0.5006   0.7598   0.9435

b Is Matrix or ndims(b) >= 3

In this situation, the right-hand side b and the subarray indexed by s1, s2, ..., sk should have exactly the same sizes. Otherwise, a size-mismatch error will be thrown.